package controllers

import (
	"context"
	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
	"go.didapinche.com/foundation/plat-echo/app/ops/models/request"
	"go.didapinche.com/foundation/plat-echo/app/ops/services"
	"go.didapinche.com/foundation/plat-echo/pkg/constants"
	"go.uber.org/zap"
	"net/http"
	"strconv"
)

type ApiController struct {
	service    services.ApiDataService
	apiService services.ApiService
	logger     *zap.Logger
}

func NewApiController(service services.ApiDataService, apiService services.ApiService, logger *zap.Logger) *ApiController {
	return &ApiController{
		service:    service,
		apiService: apiService,
		logger:     logger.With(zap.String("type", "controller.api")),
	}
}

func (ctl *ApiController) FindList(c *gin.Context) {
	param := new(request.ApiSlaRequest)
	err := c.BindQuery(param)
	if err != nil {
		ctl.logger.Error("bind param error", zap.Error(err))
		c.String(http.StatusBadRequest, err.Error())
		return
	}

	result, totalCount, err := ctl.service.Find(c.Request.Context(), param)
	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call FindListSla() error", zap.Error(err))
		c.String(http.StatusInternalServerError, "call FindListSla() error:%v", err)
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"data":        result,
		"total_count": totalCount,
	})
}

func (ctl *ApiController) FindApiSla(c *gin.Context) {
	param := new(request.ApiSlaRequest)
	err := c.BindQuery(param)
	if err != nil {
		ctl.logger.Error("bind param error", zap.Error(err))
		c.String(http.StatusBadRequest, err.Error())
		return
	}

	result, err := ctl.service.FindSla(c.Request.Context(), param)
	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call FindListSla() error", zap.Error(err))
		c.String(http.StatusInternalServerError, "call FindListSla() error:%v", err)
		return
	}

	c.JSON(http.StatusOK, result)
}

func (ctl *ApiController) FindGraphByIsForce(c *gin.Context) {
	id := c.Query("id")
	ID, err := strconv.ParseUint(id, 10, 64)
	if err != nil {
		ctl.logger.Error("bind param error", zap.Error(err))
		c.String(http.StatusBadRequest, err.Error())
		return
	}

	result, err := ctl.service.FindGraphByIsForce(c.Request.Context(), ID)
	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call FindListSla error", zap.Error(err))
		c.String(http.StatusInternalServerError, "call FindListSla() error:%v", err)
		return
	}
	c.JSON(http.StatusOK, result)
}

func (ctl *ApiController) UpdateStatus(c *gin.Context) {
	params := new(struct {
		DisableIDS []int  `form:"disable_ids" json:"disable_ids"`
		EnableIDS  []int  `form:"enable_ids" json:"enable_ids"`
		ApiID      uint64 `form:"api_id" json:"api_id"`
	})

	err := c.BindJSON(params)
	if err != nil {
		ctl.logger.Error("bind param error", zap.Error(err))
		c.String(http.StatusBadRequest, err.Error())
		return
	}

	err = ctl.apiService.UpdateStatus(c.Request.Context(), params.ApiID, params.DisableIDS, params.EnableIDS)
	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		c.String(http.StatusInternalServerError, err.Error())
		return
	}
	c.JSON(http.StatusOK, "ok")
}

func (ctl *ApiController) GetStatistics(c *gin.Context) {
	//过滤条件 时间
	start := c.Query("start")
	end := c.Query("end")
	//过滤条件 组
	group := c.Query("group_id")
	//过滤条件 级别
	level, err := strconv.ParseUint(c.Query("level"), 0, 64)
	if err != nil {
		level = 0
	}
	//默认排行榜取十个数
	pageSize, err := strconv.ParseInt(c.Query("page_size"), 0, 64)
	if err != nil || pageSize == 0 {
		pageSize = 10
	}

	name := c.Query("name")

	statistics, err := ctl.service.GetStatistics(c.Request.Context(), start, end, group, name, level, int(pageSize))
	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call GetStatistics() error", zap.Error(err))
		c.String(http.StatusInternalServerError, "call GetStatistics() error:%v", err)
		return
	}

	if statistics != nil {
		c.JSON(http.StatusOK, gin.H{
			"data": statistics.Data,
			"name": statistics.Name,
		})
		return
	}

	c.String(http.StatusBadRequest, "name is not existed:"+name)
}

func (ctl *ApiController) FindSlaStat(c *gin.Context) {
	req := new(request.OverviewReq)
	if err := c.BindQuery(req); err != nil {
		ctl.logger.Error("bind param error", zap.Error(err))
		c.String(http.StatusBadRequest, "bind param error:%v", err)
		return
	}
	stat, err := ctl.service.FindSlaStat(c.Request.Context(), req)
	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call SlaService.FindSlaStat() error", zap.Error(err))
		c.String(http.StatusInternalServerError, "call SlaService.FindSlaStat() error:%v", err)
		return
	}
	c.JSON(http.StatusOK, stat)
}

func (ctl *ApiController) FindByID(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 0, 64)
	if err != nil {
		ctl.logger.Error("convert id to integer error", zap.Error(err))
		c.String(http.StatusBadRequest, "convert id to integer error")
		return
	}

	info, err := ctl.apiService.FindByID(c.Request.Context(), id)
	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call FindByID() error", zap.Error(err))
		c.String(http.StatusInternalServerError, "call FindByID() error:%v", err)
		return
	}

	c.JSON(http.StatusOK, info)
}

func (ctl *ApiController) ClearnApiData(c *gin.Context) {
	start := c.Query("start")
	err := ctl.service.ClearnApiData(c.Request.Context(), start)
	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call FindByID() error", zap.Error(err))
		c.String(http.StatusInternalServerError, "call FindByID() error:%v", err)
		return
	}

	c.JSON(http.StatusOK, "ok")
}

func (ctl *ApiController) FindByZeusClient(c *gin.Context) {
	apiID := c.Query("api_id")
	id, err := strconv.ParseUint(apiID, 10, 64)
	if err != nil {
		ctl.logger.Error("convert id to integer error", zap.Error(err))
		c.String(http.StatusBadRequest, "convert id to integer error:%v", err)
		return
	}
	apis, err := ctl.apiService.FindByZeusClient(c.Request.Context(), id)
	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call FindByZeusClient() error", zap.Error(err))
		c.String(http.StatusInternalServerError, "call FindByZeusClient() error:%v", err)
		return
	}
	c.JSON(http.StatusOK, apis)
}
